﻿using System;
using System.Diagnostics.Contracts;

namespace OpenLS.Spreadsheet
{
    static class RangeExtensions
    {
        public static Range Projected (Range range, Worksheet worksheet)
        {
            Contract.Requires(range != null);
            Contract.Ensures(Contract.Result<Range>() != null);
            Contract.Ensures(Contract.Result<Range>().GetType() == range.GetType());
            if (range is CompositeRange)
            {
                CompositeRange cr = (CompositeRange) range;
                return new CompositeRange(Enumerable.Select(cr.Ranges, rr => ProjectedSimple(rr, worksheet)));
            }
            return worksheet.GetRange(range.Address);
        }
        public static SimpleRange ProjectedSimple(Range range, Worksheet worksheet)
        {
            return (SimpleRange) worksheet.GetRange(range.Address);
        }


        public static Range  MergeColumn (Range range, Column column, MergeType mergeType)
        {
            switch (mergeType)
            {
                case MergeType.None:
                    throw new NotImplementedException();
                case MergeType.Union:
                    return CompositeRange.Union(range, new FullColumnRange(column));
                case MergeType.Extend:
                    {
                        FullColumnRange fullColumnRange = range as FullColumnRange;
                        if (fullColumnRange != null)
                            return new FullColumnRange(fullColumnRange.anchor, column); 
                        CompositeRange compositeRange = range as CompositeRange;
                        if (compositeRange != null && compositeRange.Ranges[compositeRange.Ranges.Count - 1] is FullColumnRange)
                        {
                            FullColumnRange cr = (FullColumnRange) compositeRange.Ranges[compositeRange.Ranges.Count - 1];
                            cr = new FullColumnRange(cr.anchor, column);
                            return
                                new CompositeRange(
                                    Enumerable.Union(
                                        Enumerable.Take(compositeRange.Ranges, compositeRange.Ranges.Count - 1),
                                        new SimpleRange[] {cr}));
                        }
                        return new FullColumnRange(column);
                       
                    }
                default: throw new NotSupportedException();

            }
        }
        public static Range MergeRow(Range range, Row row, MergeType mergeType)
        {
            switch (mergeType)
            {
                case MergeType.None:
                    throw new NotImplementedException();
                case MergeType.Union:
                    return CompositeRange.Union(range, new FullRowRange(row));
                case MergeType.Extend:
                    {
                        FullRowRange fullColumnRange = range as FullRowRange;
                        if (fullColumnRange != null)
                            return new FullRowRange(fullColumnRange.anchor, row); 
                        CompositeRange compositeRange = range as CompositeRange;
                        if (compositeRange != null && compositeRange.Ranges[compositeRange.Ranges.Count - 1] is FullRowRange)
                        {
                            FullRowRange cr = (FullRowRange)compositeRange.Ranges[compositeRange.Ranges.Count - 1];
                            cr = new FullRowRange(cr.anchor, row);
                            return
                                CompositeRange.CreateWithLast(compositeRange, cr);
                                //new CompositeRange(
                                  //  Enumerable.Union(
                                    //    Enumerable.Take(compositeRange.Ranges, compositeRange.Ranges.Count - 1),
                                      //  new Range[] { cr }));
                        }
                        return new FullRowRange(row);

                        
                    }
                default: throw new NotSupportedException();

            }
        }
    }
}